package com.alex.projects.bitcask.api;

import com.alex.projects.bitcask.Tools;
import lombok.Data;

import java.nio.ByteBuffer;

@Data
public class StoreValue {

    public static final int CRC_LEN = 8;
    public static final int STSAMP_LEN = 8;
    public static final int KEY_SIZE_LEN = 2;
    public static final int VALUE_SIZE_LEN = 4;

    private byte[] crc;
    private byte[] tstamp;
    private byte[] kSz;
    private byte[] valueSz;
    private byte[] key;
    private byte[] value;

    public static StoreValue header(ByteBuffer buffer) {
        byte[] content = buffer.array();
        StoreValue ret = new StoreValue();
        int index = 0;
        ret.crc = new byte[CRC_LEN];
        for (int i = 0; i < ret.crc.length; i++) {
            ret.crc[i] = content[index++];
        }
        ret.tstamp = new byte[STSAMP_LEN];
        for (int i = 0; i < ret.tstamp.length; i++) {
            ret.tstamp[i] = content[index++];
        }
        ret.kSz = new byte[KEY_SIZE_LEN];
        for (int i = 0; i < ret.kSz.length; i++) {
            ret.kSz[i] = content[index++];
        }
        ret.valueSz = new byte[VALUE_SIZE_LEN];
        for (int i = 0; i < ret.valueSz.length; i++) {
            ret.valueSz[i] = content[index++];
        }
        return ret;
    }

    public static StoreValue getInstance(ByteBuffer buffer) {
        byte[] content = buffer.array();
        StoreValue ret = new StoreValue();
        int index = 0;
        ret.crc = new byte[CRC_LEN];
        for (int i = 0; i < ret.crc.length; i++) {
            ret.crc[i] = content[index++];
        }
        ret.tstamp = new byte[STSAMP_LEN];
        for (int i = 0; i < ret.tstamp.length; i++) {
            ret.tstamp[i] = content[index++];
        }
        ret.kSz = new byte[KEY_SIZE_LEN];
        for (int i = 0; i < ret.kSz.length; i++) {
            ret.kSz[i] = content[index++];
        }
        ret.valueSz = new byte[VALUE_SIZE_LEN];
        for (int i = 0; i < ret.valueSz.length; i++) {
            ret.valueSz[i] = content[index++];
        }
        short keyLen = Tools.bytesToShort(ret.kSz);
        if (keyLen <= 0) {
            throw new RuntimeException("key length should not below 0");
        }
        ret.key = new byte[keyLen];
        for (int i = 0; i < keyLen; i++) {
            ret.key[i] = content[index++];
        }
        int valueSz = Tools.bytesToInt(ret.valueSz);
        if (valueSz <= 0) {
            throw new RuntimeException("value length should not below 0");
        }
        ret.value = new byte[valueSz];
        for (int i = 0; i < valueSz; i++) {
            ret.value[i] = content[index++];
        }
        return ret;
    }

    public ByteBuffer[] wrap() {
        ByteBuffer[] ret = new ByteBuffer[6];
        ret[0] = ByteBuffer.wrap(crc);
        ret[1] = ByteBuffer.wrap(tstamp);
        ret[2] = ByteBuffer.wrap(kSz);
        ret[3] = ByteBuffer.wrap(valueSz);
        ret[4] = ByteBuffer.wrap(key);
        ret[5] = ByteBuffer.wrap(value);
        return ret;
    }

    public int size() {
        return crc.length + tstamp.length + kSz.length +
                valueSz.length + key.length + value.length;
    }

}
